package com.useful.web.advice;

import com.alibaba.fastjson.JSON;
import com.useful.core.api.R;
import com.useful.core.constant.GlobalConstant;
import com.useful.web.annotation.Ignore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;

/**
 * @author : wenchao.long
 * @date : Created in 2021/9/18 21:19 周六
 * @description :
 */
@Slf4j
@RestControllerAdvice
@SuppressWarnings("ALL")
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        return filter(returnType);
    }

    @Nullable
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        if (body == null) {
            // 如果 body是String类型 && body ==null 要判断
            if (GlobalConstant.STRING_CLASS.equals(returnType.getParameterType().getName())) {
                return JSON.toJSON(R.success()).toString();
            }
            return R.success();
        } else if (body instanceof R) {
            return body;
        }
        return body instanceof String ? JSON.toJSON(R.data(body)).toString() : R.data(body);
    }

    private boolean filter(MethodParameter methodParameter) {
        Class<?> declaringClass = methodParameter.getDeclaringClass();
        boolean contains;
        // 类标记了 Ignore 注解
        contains = declaringClass.isAnnotationPresent(Ignore.class);
        if (contains) {
            return false;
        }
        Method method = methodParameter.getMethod();
        // 方法标记了 Ignore 注解
        if (method != null) {
            contains = method.isAnnotationPresent(Ignore.class);
            return !contains;
        }
        return true;
    }
}
